import * as TWEEN from '@tweenjs/tween.js';

let _animating = false;

export enum EasingTypes {
  IN = 'in',
  OUT = 'out',
  INOUT = 'inout',
}

export const rotateAnimation = (
  sceneSetup,
  originInfo,
  rotateInfo,
  delay,
  easing = EasingTypes.INOUT,
) => {
  sceneSetup.rotateAnimationComplete = false;
  return new Promise<void>((resolve) => {
    let tween = new TWEEN.Tween({
      x1: originInfo.cameraPos.x,
      y1: originInfo.cameraPos.y,
      z1: originInfo.cameraPos.z,
      upx: originInfo.cameraUp.x,
      upy: originInfo.cameraUp.y,
      upz: originInfo.cameraUp.z,
      tx: originInfo.target.x,
      ty: originInfo.target.y,
      tz: originInfo.target.z,
      far: originInfo.far,
      zoom: originInfo.zoom,
    });

    tween.to(
      {
        x1: rotateInfo.cameraPos.x,
        y1: rotateInfo.cameraPos.y,
        z1: rotateInfo.cameraPos.z,
        upx: rotateInfo.cameraUp.x,
        upy: rotateInfo.cameraUp.y,
        upz: rotateInfo.cameraUp.z,
        tx: rotateInfo.target.x,
        ty: rotateInfo.target.y,
        tz: rotateInfo.target.z,
        far: rotateInfo.far,
        zoom: rotateInfo.zoom,
      },
      delay,
    );

    tween.start();

    tween.onUpdate(function (Object) {
      sceneSetup.trackballControls.applyRotateInfo(Object);
    });

    if (easing === EasingTypes.IN) {
      tween.easing(TWEEN.Easing.Sinusoidal.In);
    } else if (easing === EasingTypes.OUT) {
      tween.easing(TWEEN.Easing.Sinusoidal.Out);
    } else {
      tween.easing(TWEEN.Easing.Cubic.InOut);
    }

    tween.onComplete(function () {
      _animating = false;
      sceneSetup.rotateAnimationComplete = true;
      resolve();
    });
    _animating = true;
    doAnimate();
  });
};

function doAnimate() {
  if (!_animating) return;
  requestAnimationFrame(doAnimate);
  TWEEN.update();
}
